1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkState;
21 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
22 import static com.google.common.collect.CollectPreconditions.checkRemove;
23
24 import com.google.common.annotations.GwtCompatible;
25 import com.google.common.annotations.GwtIncompatible;
26 import com.google.common.base.MoreObjects;
27 import com.google.common.primitives.Ints;
28
29 import java.io.IOException;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32 import java.io.Serializable;
33 import java.util.Comparator;
34 import java.util.ConcurrentModificationException;
35 import java.util.Iterator;
36 import java.util.NoSuchElementException;
37
38 import javax.annotation.Nullable;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 @GwtCompatible(emulated = true)
59 public final class TreeMultiset<E> extends AbstractSortedMultiset<E> implements Serializable {
60
61
62
63
64
65
66
67
68
69
70
71
72
73 public static <E extends Comparable> TreeMultiset<E> create() {
74 return new TreeMultiset<E>(Ordering.natural());
75 }
76
77
78
79
80
81
82
83
84
85
86
87
88
89 @SuppressWarnings("unchecked")
90 public static <E> TreeMultiset<E> create(@Nullable Comparator<? super E> comparator) {
91 return (comparator == null)
92 ? new TreeMultiset<E>((Comparator) Ordering.natural())
93 : new TreeMultiset<E>(comparator);
94 }
95
96
97
98
99
100
101
102
103
104
105 public static <E extends Comparable> TreeMultiset<E> create(Iterable<? extends E> elements) {
106 TreeMultiset<E> multiset = create();
107 Iterables.addAll(multiset, elements);
108 return multiset;
109 }
110
111 private final transient Reference<AvlNode<E>> rootReference;
112 private final transient GeneralRange<E> range;
113 private final transient AvlNode<E> header;
114
115 TreeMultiset(Reference<AvlNode<E>> rootReference, GeneralRange<E> range, AvlNode<E> endLink) {
116 super(range.comparator());
117 this.rootReference = rootReference;
118 this.range = range;
119 this.header = endLink;
120 }
121
122 TreeMultiset(Comparator<? super E> comparator) {
123 super(comparator);
124 this.range = GeneralRange.all(comparator);
125 this.header = new AvlNode<E>(null, 1);
126 successor(header, header);
127 this.rootReference = new Reference<AvlNode<E>>();
128 }
129
130
131
132
133 private enum Aggregate {
134 SIZE {
135 @Override
136 int nodeAggregate(AvlNode<?> node) {
137 return node.elemCount;
138 }
139
140 @Override
141 long treeAggregate(@Nullable AvlNode<?> root) {
142 return (root == null) ? 0 : root.totalCount;
143 }
144 },
145 DISTINCT {
146 @Override
147 int nodeAggregate(AvlNode<?> node) {
148 return 1;
149 }
150
151 @Override
152 long treeAggregate(@Nullable AvlNode<?> root) {
153 return (root == null) ? 0 : root.distinctElements;
154 }
155 };
156 abstract int nodeAggregate(AvlNode<?> node);
157
158 abstract long treeAggregate(@Nullable AvlNode<?> root);
159 }
160
161 private long aggregateForEntries(Aggregate aggr) {
162 AvlNode<E> root = rootReference.get();
163 long total = aggr.treeAggregate(root);
164 if (range.hasLowerBound()) {
165 total -= aggregateBelowRange(aggr, root);
166 }
167 if (range.hasUpperBound()) {
168 total -= aggregateAboveRange(aggr, root);
169 }
170 return total;
171 }
172
173 private long aggregateBelowRange(Aggregate aggr, @Nullable AvlNode<E> node) {
174 if (node == null) {
175 return 0;
176 }
177 int cmp = comparator().compare(range.getLowerEndpoint(), node.elem);
178 if (cmp < 0) {
179 return aggregateBelowRange(aggr, node.left);
180 } else if (cmp == 0) {
181 switch (range.getLowerBoundType()) {
182 case OPEN:
183 return aggr.nodeAggregate(node) + aggr.treeAggregate(node.left);
184 case CLOSED:
185 return aggr.treeAggregate(node.left);
186 default:
187 throw new AssertionError();
188 }
189 } else {
190 return aggr.treeAggregate(node.left) + aggr.nodeAggregate(node)
191 + aggregateBelowRange(aggr, node.right);
192 }
193 }
194
195 private long aggregateAboveRange(Aggregate aggr, @Nullable AvlNode<E> node) {
196 if (node == null) {
197 return 0;
198 }
199 int cmp = comparator().compare(range.getUpperEndpoint(), node.elem);
200 if (cmp > 0) {
201 return aggregateAboveRange(aggr, node.right);
202 } else if (cmp == 0) {
203 switch (range.getUpperBoundType()) {
204 case OPEN:
205 return aggr.nodeAggregate(node) + aggr.treeAggregate(node.right);
206 case CLOSED:
207 return aggr.treeAggregate(node.right);
208 default:
209 throw new AssertionError();
210 }
211 } else {
212 return aggr.treeAggregate(node.right) + aggr.nodeAggregate(node)
213 + aggregateAboveRange(aggr, node.left);
214 }
215 }
216
217 @Override
218 public int size() {
219 return Ints.saturatedCast(aggregateForEntries(Aggregate.SIZE));
220 }
221
222 @Override
223 int distinctElements() {
224 return Ints.saturatedCast(aggregateForEntries(Aggregate.DISTINCT));
225 }
226
227 @Override
228 public int count(@Nullable Object element) {
229 try {
230 @SuppressWarnings("unchecked")
231 E e = (E) element;
232 AvlNode<E> root = rootReference.get();
233 if (!range.contains(e) || root == null) {
234 return 0;
235 }
236 return root.count(comparator(), e);
237 } catch (ClassCastException e) {
238 return 0;
239 } catch (NullPointerException e) {
240 return 0;
241 }
242 }
243
244 @Override
245 public int add(@Nullable E element, int occurrences) {
246 checkNonnegative(occurrences, "occurrences");
247 if (occurrences == 0) {
248 return count(element);
249 }
250 checkArgument(range.contains(element));
251 AvlNode<E> root = rootReference.get();
252 if (root == null) {
253 comparator().compare(element, element);
254 AvlNode<E> newRoot = new AvlNode<E>(element, occurrences);
255 successor(header, newRoot, header);
256 rootReference.checkAndSet(root, newRoot);
257 return 0;
258 }
259 int[] result = new int[1];
260 AvlNode<E> newRoot = root.add(comparator(), element, occurrences, result);
261 rootReference.checkAndSet(root, newRoot);
262 return result[0];
263 }
264
265 @Override
266 public int remove(@Nullable Object element, int occurrences) {
267 checkNonnegative(occurrences, "occurrences");
268 if (occurrences == 0) {
269 return count(element);
270 }
271 AvlNode<E> root = rootReference.get();
272 int[] result = new int[1];
273 AvlNode<E> newRoot;
274 try {
275 @SuppressWarnings("unchecked")
276 E e = (E) element;
277 if (!range.contains(e) || root == null) {
278 return 0;
279 }
280 newRoot = root.remove(comparator(), e, occurrences, result);
281 } catch (ClassCastException e) {
282 return 0;
283 } catch (NullPointerException e) {
284 return 0;
285 }
286 rootReference.checkAndSet(root, newRoot);
287 return result[0];
288 }
289
290 @Override
291 public int setCount(@Nullable E element, int count) {
292 checkNonnegative(count, "count");
293 if (!range.contains(element)) {
294 checkArgument(count == 0);
295 return 0;
296 }
297
298 AvlNode<E> root = rootReference.get();
299 if (root == null) {
300 if (count > 0) {
301 add(element, count);
302 }
303 return 0;
304 }
305 int[] result = new int[1];
306 AvlNode<E> newRoot = root.setCount(comparator(), element, count, result);
307 rootReference.checkAndSet(root, newRoot);
308 return result[0];
309 }
310
311 @Override
312 public boolean setCount(@Nullable E element, int oldCount, int newCount) {
313 checkNonnegative(newCount, "newCount");
314 checkNonnegative(oldCount, "oldCount");
315 checkArgument(range.contains(element));
316
317 AvlNode<E> root = rootReference.get();
318 if (root == null) {
319 if (oldCount == 0) {
320 if (newCount > 0) {
321 add(element, newCount);
322 }
323 return true;
324 } else {
325 return false;
326 }
327 }
328 int[] result = new int[1];
329 AvlNode<E> newRoot = root.setCount(comparator(), element, oldCount, newCount, result);
330 rootReference.checkAndSet(root, newRoot);
331 return result[0] == oldCount;
332 }
333
334 private Entry<E> wrapEntry(final AvlNode<E> baseEntry) {
335 return new Multisets.AbstractEntry<E>() {
336 @Override
337 public E getElement() {
338 return baseEntry.getElement();
339 }
340
341 @Override
342 public int getCount() {
343 int result = baseEntry.getCount();
344 if (result == 0) {
345 return count(getElement());
346 } else {
347 return result;
348 }
349 }
350 };
351 }
352
353
354
355
356 @Nullable private AvlNode<E> firstNode() {
357 AvlNode<E> root = rootReference.get();
358 if (root == null) {
359 return null;
360 }
361 AvlNode<E> node;
362 if (range.hasLowerBound()) {
363 E endpoint = range.getLowerEndpoint();
364 node = rootReference.get().ceiling(comparator(), endpoint);
365 if (node == null) {
366 return null;
367 }
368 if (range.getLowerBoundType() == BoundType.OPEN
369 && comparator().compare(endpoint, node.getElement()) == 0) {
370 node = node.succ;
371 }
372 } else {
373 node = header.succ;
374 }
375 return (node == header || !range.contains(node.getElement())) ? null : node;
376 }
377
378 @Nullable private AvlNode<E> lastNode() {
379 AvlNode<E> root = rootReference.get();
380 if (root == null) {
381 return null;
382 }
383 AvlNode<E> node;
384 if (range.hasUpperBound()) {
385 E endpoint = range.getUpperEndpoint();
386 node = rootReference.get().floor(comparator(), endpoint);
387 if (node == null) {
388 return null;
389 }
390 if (range.getUpperBoundType() == BoundType.OPEN
391 && comparator().compare(endpoint, node.getElement()) == 0) {
392 node = node.pred;
393 }
394 } else {
395 node = header.pred;
396 }
397 return (node == header || !range.contains(node.getElement())) ? null : node;
398 }
399
400 @Override
401 Iterator<Entry<E>> entryIterator() {
402 return new Iterator<Entry<E>>() {
403 AvlNode<E> current = firstNode();
404 Entry<E> prevEntry;
405
406 @Override
407 public boolean hasNext() {
408 if (current == null) {
409 return false;
410 } else if (range.tooHigh(current.getElement())) {
411 current = null;
412 return false;
413 } else {
414 return true;
415 }
416 }
417
418 @Override
419 public Entry<E> next() {
420 if (!hasNext()) {
421 throw new NoSuchElementException();
422 }
423 Entry<E> result = wrapEntry(current);
424 prevEntry = result;
425 if (current.succ == header) {
426 current = null;
427 } else {
428 current = current.succ;
429 }
430 return result;
431 }
432
433 @Override
434 public void remove() {
435 checkRemove(prevEntry != null);
436 setCount(prevEntry.getElement(), 0);
437 prevEntry = null;
438 }
439 };
440 }
441
442 @Override
443 Iterator<Entry<E>> descendingEntryIterator() {
444 return new Iterator<Entry<E>>() {
445 AvlNode<E> current = lastNode();
446 Entry<E> prevEntry = null;
447
448 @Override
449 public boolean hasNext() {
450 if (current == null) {
451 return false;
452 } else if (range.tooLow(current.getElement())) {
453 current = null;
454 return false;
455 } else {
456 return true;
457 }
458 }
459
460 @Override
461 public Entry<E> next() {
462 if (!hasNext()) {
463 throw new NoSuchElementException();
464 }
465 Entry<E> result = wrapEntry(current);
466 prevEntry = result;
467 if (current.pred == header) {
468 current = null;
469 } else {
470 current = current.pred;
471 }
472 return result;
473 }
474
475 @Override
476 public void remove() {
477 checkRemove(prevEntry != null);
478 setCount(prevEntry.getElement(), 0);
479 prevEntry = null;
480 }
481 };
482 }
483
484 @Override
485 public SortedMultiset<E> headMultiset(@Nullable E upperBound, BoundType boundType) {
486 return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.upTo(
487 comparator(),
488 upperBound,
489 boundType)), header);
490 }
491
492 @Override
493 public SortedMultiset<E> tailMultiset(@Nullable E lowerBound, BoundType boundType) {
494 return new TreeMultiset<E>(rootReference, range.intersect(GeneralRange.downTo(
495 comparator(),
496 lowerBound,
497 boundType)), header);
498 }
499
500 static int distinctElements(@Nullable AvlNode<?> node) {
501 return (node == null) ? 0 : node.distinctElements;
502 }
503
504 private static final class Reference<T> {
505 @Nullable private T value;
506
507 @Nullable public T get() {
508 return value;
509 }
510
511 public void checkAndSet(@Nullable T expected, T newValue) {
512 if (value != expected) {
513 throw new ConcurrentModificationException();
514 }
515 value = newValue;
516 }
517 }
518
519 private static final class AvlNode<E> extends Multisets.AbstractEntry<E> {
520 @Nullable private final E elem;
521
522
523 private int elemCount;
524
525 private int distinctElements;
526 private long totalCount;
527 private int height;
528 private AvlNode<E> left;
529 private AvlNode<E> right;
530 private AvlNode<E> pred;
531 private AvlNode<E> succ;
532
533 AvlNode(@Nullable E elem, int elemCount) {
534 checkArgument(elemCount > 0);
535 this.elem = elem;
536 this.elemCount = elemCount;
537 this.totalCount = elemCount;
538 this.distinctElements = 1;
539 this.height = 1;
540 this.left = null;
541 this.right = null;
542 }
543
544 public int count(Comparator<? super E> comparator, E e) {
545 int cmp = comparator.compare(e, elem);
546 if (cmp < 0) {
547 return (left == null) ? 0 : left.count(comparator, e);
548 } else if (cmp > 0) {
549 return (right == null) ? 0 : right.count(comparator, e);
550 } else {
551 return elemCount;
552 }
553 }
554
555 private AvlNode<E> addRightChild(E e, int count) {
556 right = new AvlNode<E>(e, count);
557 successor(this, right, succ);
558 height = Math.max(2, height);
559 distinctElements++;
560 totalCount += count;
561 return this;
562 }
563
564 private AvlNode<E> addLeftChild(E e, int count) {
565 left = new AvlNode<E>(e, count);
566 successor(pred, left, this);
567 height = Math.max(2, height);
568 distinctElements++;
569 totalCount += count;
570 return this;
571 }
572
573 AvlNode<E> add(Comparator<? super E> comparator, @Nullable E e, int count, int[] result) {
574
575
576
577
578 int cmp = comparator.compare(e, elem);
579 if (cmp < 0) {
580 AvlNode<E> initLeft = left;
581 if (initLeft == null) {
582 result[0] = 0;
583 return addLeftChild(e, count);
584 }
585 int initHeight = initLeft.height;
586
587 left = initLeft.add(comparator, e, count, result);
588 if (result[0] == 0) {
589 distinctElements++;
590 }
591 this.totalCount += count;
592 return (left.height == initHeight) ? this : rebalance();
593 } else if (cmp > 0) {
594 AvlNode<E> initRight = right;
595 if (initRight == null) {
596 result[0] = 0;
597 return addRightChild(e, count);
598 }
599 int initHeight = initRight.height;
600
601 right = initRight.add(comparator, e, count, result);
602 if (result[0] == 0) {
603 distinctElements++;
604 }
605 this.totalCount += count;
606 return (right.height == initHeight) ? this : rebalance();
607 }
608
609
610 result[0] = elemCount;
611 long resultCount = (long) elemCount + count;
612 checkArgument(resultCount <= Integer.MAX_VALUE);
613 this.elemCount += count;
614 this.totalCount += count;
615 return this;
616 }
617
618 AvlNode<E> remove(Comparator<? super E> comparator, @Nullable E e, int count, int[] result) {
619 int cmp = comparator.compare(e, elem);
620 if (cmp < 0) {
621 AvlNode<E> initLeft = left;
622 if (initLeft == null) {
623 result[0] = 0;
624 return this;
625 }
626
627 left = initLeft.remove(comparator, e, count, result);
628
629 if (result[0] > 0) {
630 if (count >= result[0]) {
631 this.distinctElements--;
632 this.totalCount -= result[0];
633 } else {
634 this.totalCount -= count;
635 }
636 }
637 return (result[0] == 0) ? this : rebalance();
638 } else if (cmp > 0) {
639 AvlNode<E> initRight = right;
640 if (initRight == null) {
641 result[0] = 0;
642 return this;
643 }
644
645 right = initRight.remove(comparator, e, count, result);
646
647 if (result[0] > 0) {
648 if (count >= result[0]) {
649 this.distinctElements--;
650 this.totalCount -= result[0];
651 } else {
652 this.totalCount -= count;
653 }
654 }
655 return rebalance();
656 }
657
658
659 result[0] = elemCount;
660 if (count >= elemCount) {
661 return deleteMe();
662 } else {
663 this.elemCount -= count;
664 this.totalCount -= count;
665 return this;
666 }
667 }
668
669 AvlNode<E> setCount(Comparator<? super E> comparator, @Nullable E e, int count, int[] result) {
670 int cmp = comparator.compare(e, elem);
671 if (cmp < 0) {
672 AvlNode<E> initLeft = left;
673 if (initLeft == null) {
674 result[0] = 0;
675 return (count > 0) ? addLeftChild(e, count) : this;
676 }
677
678 left = initLeft.setCount(comparator, e, count, result);
679
680 if (count == 0 && result[0] != 0) {
681 this.distinctElements--;
682 } else if (count > 0 && result[0] == 0) {
683 this.distinctElements++;
684 }
685
686 this.totalCount += count - result[0];
687 return rebalance();
688 } else if (cmp > 0) {
689 AvlNode<E> initRight = right;
690 if (initRight == null) {
691 result[0] = 0;
692 return (count > 0) ? addRightChild(e, count) : this;
693 }
694
695 right = initRight.setCount(comparator, e, count, result);
696
697 if (count == 0 && result[0] != 0) {
698 this.distinctElements--;
699 } else if (count > 0 && result[0] == 0) {
700 this.distinctElements++;
701 }
702
703 this.totalCount += count - result[0];
704 return rebalance();
705 }
706
707
708 result[0] = elemCount;
709 if (count == 0) {
710 return deleteMe();
711 }
712 this.totalCount += count - elemCount;
713 this.elemCount = count;
714 return this;
715 }
716
717 AvlNode<E> setCount(
718 Comparator<? super E> comparator,
719 @Nullable E e,
720 int expectedCount,
721 int newCount,
722 int[] result) {
723 int cmp = comparator.compare(e, elem);
724 if (cmp < 0) {
725 AvlNode<E> initLeft = left;
726 if (initLeft == null) {
727 result[0] = 0;
728 if (expectedCount == 0 && newCount > 0) {
729 return addLeftChild(e, newCount);
730 }
731 return this;
732 }
733
734 left = initLeft.setCount(comparator, e, expectedCount, newCount, result);
735
736 if (result[0] == expectedCount) {
737 if (newCount == 0 && result[0] != 0) {
738 this.distinctElements--;
739 } else if (newCount > 0 && result[0] == 0) {
740 this.distinctElements++;
741 }
742 this.totalCount += newCount - result[0];
743 }
744 return rebalance();
745 } else if (cmp > 0) {
746 AvlNode<E> initRight = right;
747 if (initRight == null) {
748 result[0] = 0;
749 if (expectedCount == 0 && newCount > 0) {
750 return addRightChild(e, newCount);
751 }
752 return this;
753 }
754
755 right = initRight.setCount(comparator, e, expectedCount, newCount, result);
756
757 if (result[0] == expectedCount) {
758 if (newCount == 0 && result[0] != 0) {
759 this.distinctElements--;
760 } else if (newCount > 0 && result[0] == 0) {
761 this.distinctElements++;
762 }
763 this.totalCount += newCount - result[0];
764 }
765 return rebalance();
766 }
767
768
769 result[0] = elemCount;
770 if (expectedCount == elemCount) {
771 if (newCount == 0) {
772 return deleteMe();
773 }
774 this.totalCount += newCount - elemCount;
775 this.elemCount = newCount;
776 }
777 return this;
778 }
779
780 private AvlNode<E> deleteMe() {
781 int oldElemCount = this.elemCount;
782 this.elemCount = 0;
783 successor(pred, succ);
784 if (left == null) {
785 return right;
786 } else if (right == null) {
787 return left;
788 } else if (left.height >= right.height) {
789 AvlNode<E> newTop = pred;
790
791 newTop.left = left.removeMax(newTop);
792 newTop.right = right;
793 newTop.distinctElements = distinctElements - 1;
794 newTop.totalCount = totalCount - oldElemCount;
795 return newTop.rebalance();
796 } else {
797 AvlNode<E> newTop = succ;
798 newTop.right = right.removeMin(newTop);
799 newTop.left = left;
800 newTop.distinctElements = distinctElements - 1;
801 newTop.totalCount = totalCount - oldElemCount;
802 return newTop.rebalance();
803 }
804 }
805
806
807 private AvlNode<E> removeMin(AvlNode<E> node) {
808 if (left == null) {
809 return right;
810 } else {
811 left = left.removeMin(node);
812 distinctElements--;
813 totalCount -= node.elemCount;
814 return rebalance();
815 }
816 }
817
818
819 private AvlNode<E> removeMax(AvlNode<E> node) {
820 if (right == null) {
821 return left;
822 } else {
823 right = right.removeMax(node);
824 distinctElements--;
825 totalCount -= node.elemCount;
826 return rebalance();
827 }
828 }
829
830 private void recomputeMultiset() {
831 this.distinctElements = 1 + TreeMultiset.distinctElements(left)
832 + TreeMultiset.distinctElements(right);
833 this.totalCount = elemCount + totalCount(left) + totalCount(right);
834 }
835
836 private void recomputeHeight() {
837 this.height = 1 + Math.max(height(left), height(right));
838 }
839
840 private void recompute() {
841 recomputeMultiset();
842 recomputeHeight();
843 }
844
845 private AvlNode<E> rebalance() {
846 switch (balanceFactor()) {
847 case -2:
848 if (right.balanceFactor() > 0) {
849 right = right.rotateRight();
850 }
851 return rotateLeft();
852 case 2:
853 if (left.balanceFactor() < 0) {
854 left = left.rotateLeft();
855 }
856 return rotateRight();
857 default:
858 recomputeHeight();
859 return this;
860 }
861 }
862
863 private int balanceFactor() {
864 return height(left) - height(right);
865 }
866
867 private AvlNode<E> rotateLeft() {
868 checkState(right != null);
869 AvlNode<E> newTop = right;
870 this.right = newTop.left;
871 newTop.left = this;
872 newTop.totalCount = this.totalCount;
873 newTop.distinctElements = this.distinctElements;
874 this.recompute();
875 newTop.recomputeHeight();
876 return newTop;
877 }
878
879 private AvlNode<E> rotateRight() {
880 checkState(left != null);
881 AvlNode<E> newTop = left;
882 this.left = newTop.right;
883 newTop.right = this;
884 newTop.totalCount = this.totalCount;
885 newTop.distinctElements = this.distinctElements;
886 this.recompute();
887 newTop.recomputeHeight();
888 return newTop;
889 }
890
891 private static long totalCount(@Nullable AvlNode<?> node) {
892 return (node == null) ? 0 : node.totalCount;
893 }
894
895 private static int height(@Nullable AvlNode<?> node) {
896 return (node == null) ? 0 : node.height;
897 }
898
899 @Nullable private AvlNode<E> ceiling(Comparator<? super E> comparator, E e) {
900 int cmp = comparator.compare(e, elem);
901 if (cmp < 0) {
902 return (left == null) ? this : MoreObjects.firstNonNull(left.ceiling(comparator, e), this);
903 } else if (cmp == 0) {
904 return this;
905 } else {
906 return (right == null) ? null : right.ceiling(comparator, e);
907 }
908 }
909
910 @Nullable private AvlNode<E> floor(Comparator<? super E> comparator, E e) {
911 int cmp = comparator.compare(e, elem);
912 if (cmp > 0) {
913 return (right == null) ? this : MoreObjects.firstNonNull(right.floor(comparator, e), this);
914 } else if (cmp == 0) {
915 return this;
916 } else {
917 return (left == null) ? null : left.floor(comparator, e);
918 }
919 }
920
921 @Override
922 public E getElement() {
923 return elem;
924 }
925
926 @Override
927 public int getCount() {
928 return elemCount;
929 }
930
931 @Override
932 public String toString() {
933 return Multisets.immutableEntry(getElement(), getCount()).toString();
934 }
935 }
936
937 private static <T> void successor(AvlNode<T> a, AvlNode<T> b) {
938 a.succ = b;
939 b.pred = a;
940 }
941
942 private static <T> void successor(AvlNode<T> a, AvlNode<T> b, AvlNode<T> c) {
943 successor(a, b);
944 successor(b, c);
945 }
946
947
948
949
950
951
952
953
954
955
956
957 @GwtIncompatible("java.io.ObjectOutputStream")
958 private void writeObject(ObjectOutputStream stream) throws IOException {
959 stream.defaultWriteObject();
960 stream.writeObject(elementSet().comparator());
961 Serialization.writeMultiset(this, stream);
962 }
963
964 @GwtIncompatible("java.io.ObjectInputStream")
965 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
966 stream.defaultReadObject();
967 @SuppressWarnings("unchecked")
968
969 Comparator<? super E> comparator = (Comparator<? super E>) stream.readObject();
970 Serialization.getFieldSetter(AbstractSortedMultiset.class, "comparator").set(this, comparator);
971 Serialization.getFieldSetter(TreeMultiset.class, "range").set(
972 this,
973 GeneralRange.all(comparator));
974 Serialization.getFieldSetter(TreeMultiset.class, "rootReference").set(
975 this,
976 new Reference<AvlNode<E>>());
977 AvlNode<E> header = new AvlNode<E>(null, 1);
978 Serialization.getFieldSetter(TreeMultiset.class, "header").set(this, header);
979 successor(header, header);
980 Serialization.populateMultiset(this, stream);
981 }
982
983 @GwtIncompatible("not needed in emulated source") private static final long serialVersionUID = 1;
984 }